package org.hanbo.code.repository.persistence.entity;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Text;

@PersistenceCapable
public class CodeSnippet
{
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Key key;
	
	@Persistent
	private String authorEmail;
	
	@Persistent
	private Date createDate;
	
	@Persistent
	private String subject;

	@Persistent
	private String relatedMethods;

	@Persistent
	private String keywords;

	@Persistent
	private String languageType;
	
	@Persistent
	private String referenceLink;
	
	@Persistent
	private boolean availableToPublic;
	
	@Persistent
	private Text codeSnippet;

	@Persistent
	private Text comments;

	//@Persistent
	//private Text parsedKeywords;

	public CodeSnippet()
	{
		availableToPublic = false;
	}
	
	public Key getId()
	{
		return this.key;
	}
	
	public String getAuthorEmail()
	{
		return this.authorEmail;
	}

	public void setAuthorEmail(String authorEmail)
	{
		this.authorEmail = authorEmail;
	}

	public void createDateSubmitted()
	{
		Calendar dateNow = Calendar.getInstance();
		this.createDate = dateNow.getTime();
	}
	
	public void setCreateDate(Date createDate)
	{
		this.createDate = createDate;		
	}
	
	public Date getSubmissionDate()
	{
		return this.createDate;
	}
	
	public Calendar getSubmissionDateAsCalendar()
	{
		Calendar dateNow = Calendar.getInstance();
		dateNow.setTime(this.createDate);
		
		return dateNow;
	}
	
	public String getSubmissionDateAsString()
	{		
		SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
		String retVal = format.format(this.createDate);
		
		return retVal;
	}

	public void setSubject(String subjectVal)
	{
		this.subject = subjectVal;
	}

	public String getSubject()
	{
		return this.subject;
	}
	
	public void setRelatedMethods(List<String> methods)
	{
		this.relatedMethods = convertArrayListToString(methods);
	}

	public List<String> getRelatedMethods()
	{
		return convertStringToArrayList(this.relatedMethods);
	}
	
	public void setKeywords(List<String> keywords)
	{
		this.keywords = convertArrayListToString(keywords);
	}

	public List<String> getKeywords()
	{
		return convertStringToArrayList(this.keywords);
	}

	public void setLanguageType(String langType)
	{
		this.languageType = langType;
	}

	public String getLanguageType()
	{
		return this.languageType;
	}

	public void setReferenceLink(String link)
	{
		this.referenceLink = link;
	}

	public String getReferenceLink()
	{
		return this.referenceLink;
	}

	public void setAvailabilityToPublic(boolean isAvailable)
	{
		this.availableToPublic = isAvailable;
	}

	public boolean isAvailableTpPublic()
	{
		return this.availableToPublic;
	}

	public void setCodeSnippet(String codeSnippet)
	{
		this.codeSnippet = new Text(codeSnippet);
		
		// XXX Parse code Snippet
		/*try
		{
			List<String> parsedKeywords
				= parseCodeSnippet(codeSnippet);
			this.parsedKeywords = new Text(
				convertArrayListToString(parsedKeywords)
			);
		}
		catch(IOException e)
		{
			throw new RuntimeException("Unable to parse the code snippet for keywords", e);
		}*/
	}

	public String getCodeSnippet()
	{
		return this.codeSnippet.getValue();
	}
	
	/*public List<String> getParsedKeyWords()
	{
		String parsedKeywords = this.parsedKeywords.getValue();
		return convertStringToArrayList(parsedKeywords);
	}*/
	
	public void setCodeComments(String codeComments)
	{
		this.comments = new Text(codeComments);
	}

	public String getCodeComments()
	{
		return this.comments.getValue();
	}
	
	public boolean isCodeSnippetDataValid()
	{
		return createDate !=  null
			&& (authorEmail != null && authorEmail.length() > 0)
			&& (subject != null && subject.length() > 0)
			&& (keywords != null && keywords.length() > 0)
			&& (languageType != null && languageType.length() > 0)
			&& (codeSnippet != null
				&& codeSnippet.getValue() != null 
				&& codeSnippet.getValue().length() > 0);
	}
	
	/*private List<String> parseCodeSnippet(String codeSnippet)
		throws IOException
	{
		// XXX use language type to find code parser for parse the
		// code snippet for content keywords -- Make this method obsolete.
		StringReader reader = null;
		try
		{
			Set<String> parsedKeywords = new HashSet<String>();
			
			reader = new StringReader(codeSnippet);
			int charRet = reader.read();
			StringBuilder sb = new StringBuilder();
			while (charRet != -1)
			{
				if (Character.isLetterOrDigit(charRet)
					|| charRet == (int)('_')
					|| charRet == (int)('.'))
				{
					sb.append((char)charRet);
				}
				else
				{
					String parsedKeyword = sb.toString();
					if (parsedKeyword != null && parsedKeyword.length() > 0)
					{
						parsedKeywords.add(parsedKeyword);
					}
					sb = new StringBuilder();
				}
				charRet = reader.read();
			}
			
			Iterator<String> it = parsedKeywords.iterator();
			ArrayList<String> retKeywordList = new ArrayList<String>();
			while(it.hasNext())
			{
				retKeywordList.add(it.next());
			}
			
			return retKeywordList;
		}
		finally
		{
			if (reader != null) reader.close();
		}
	}*/
	
	public static String convertArrayListToString(List<String> elements)
	{
		StringBuilder sb = new StringBuilder();
		for(String element : elements)
		{
			sb.append(element);
			sb.append(",");
		}
		return sb.toString();
	}

	public static List<String> convertStringToArrayList(String elements)
	{
		String[] arr_retVals = elements.split(",");
		ArrayList<String> retVals = new ArrayList<String>();
		for(String element : arr_retVals)
		{
			if (element != null && element.length() > 0)
			{
				retVals.add(element);
			}
		}
		
		return retVals;
	}
}
